#include <func.h>

//接收确定的字节数的数据
int recvn(int sockfd, void * buff, int len)
{
    int left = len;
    char * pbuf = buff;
    int ret = -1;
    while(left > 0) {
        ret = recv(sockfd, pbuf, left, 0);
        if(ret == 0) {
            break;
        } else if(ret < 0) {
            perror("recv");
            return -1;
        }
        left -= ret;
        pbuf += ret;
    }
    return len - left;
}

int main()
{
    //创建客户端的套接字
    int clientfd = socket(AF_INET, SOCK_STREAM, 0);
    ERROR_CHECK(clientfd, -1, "socket");

    struct sockaddr_in serveraddr;
    memset(&serveraddr, 0, sizeof(serveraddr));
    //指定使用的是IPv4的地址类型 AF_INET
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(8080);
    serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    //连接服务器
    int ret = connect(clientfd, (struct sockaddr*)&serveraddr, 
                      sizeof(serveraddr));
    ERROR_CHECK(ret, -1, "connect");
    printf("connect success.\n");

    //进行文件的接收
    //1. 先接收文件的名字
    //1.1 先接收文件名的长度
    int length = 0;
    ret = recvn(clientfd, &length, sizeof(length));
    printf("filename length: %d\n", length);
    //1.2 再接收文件名本身
    char buff[1000] = {0};
    ret = recvn(clientfd, buff, length);
    printf("1 recv ret: %d\n", ret);
    int fd = open(buff, O_CREAT|O_RDWR, 0644);
    ERROR_CHECK(fd, -1, "open");

    //2. 再接收文件的内容
    //2.1 先接收文件内容的长度
    ret = recvn(clientfd, &length, sizeof(length));
    printf("fileconent length: %d\n", length);

    int total = 0;
    int len = 0;//每一个分片的长度
    //2.2 再接收文件内容本身
    while(total < length) {
        ret = recvn(clientfd, &len, sizeof(len));
        if(len != 1000) {
            printf("slice len: %d\n", len);
            //printf("total: %d bytes.\n", total);
        }
        memset(buff, 0, sizeof(buff));
        ret = recvn(clientfd, buff, len);
        if(ret != 1000) {
            //printf("slice %d bytes.\n", ret);
        }
        if(ret > 0) {
            total += ret;
            write(fd, buff, ret);//写入本地文件
        }
    }

    close(fd);
    close(clientfd);

    return 0;
}
